// Copyright 叶湘 ( weixin:yexiang841, email:yexiang841@qq.com ), Shitouren Studio. All Rights Reserved.

#include "Property/Q3D_CPPC_PropertyState.h"
#include "Engine/DataTable.h"
#include "Hit/Q3D_CPPU_Hit.h"
#include "Property/Q3D_CPPU_PropertyState.h"
#include "Property/Q3D_CPPS_PropertyInit.h"
#include "Property/Q3D_CPPU_PropertyPLIPro.h"
#include "Logger/Q3D_CPPU_Logger.h"

// Sets default values for this component's properties
UQ3D_CPPC_PropertyState::UQ3D_CPPC_PropertyState()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;

	// ...
}

// Called when the game starts
void UQ3D_CPPC_PropertyState::BeginPlay()
{
	Super::BeginPlay();

	// ...

	this->UQ3D_CPPC_PropertyState::Q3D_F_Model_Init();
}

// Called every frame
void UQ3D_CPPC_PropertyState::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// ...
}

void UQ3D_CPPC_PropertyState::Q3D_F_Model_Init()
{
	this->Ptr_U_PropertyState = NewObject<UQ3D_CPPU_PropertyState>(this->GetOwner());
	this->Ptr_U_PropertyState->Ptr_A_Owner = this->GetOwner();

	// 下面这段是自动从宿主取 DT 对 PropertyState 进行初始化。
	// 原先构思是宿主只需要提供 DT 接口就好。
	// 但想想宿主毕竟还是要对属性之间的关联等进行细致管理，不适合做成傻瓜式 Component。
	// 就还是由宿主来调 Q3D_F_Model_Set()吧
	// 所以这一段先注掉，暂时保留 Q3D_IF_ProppertyInit_GetDT 接口，到时候要改回来也方便一点。
	/* 
	AActor* ptr_a_owner = Cast<AActor>( this->GetOwner() );
	IQ3D_CPPI_PropertyState* ptr_i_property_state_owner = Cast<IQ3D_CPPI_PropertyState>( ptr_a_owner );
	if( ! ptr_i_property_state_owner ){
		Q3D_LOG( Warning, "Cast_To_Q3D_CPPI_PropertyState_Failed" );
		return;
	}
	UDataTable* ptr_dt_property_init_tmp;
	ptr_i_property_state_owner->Execute_Q3D_IF_PropertyState_InitDT_Get( ptr_a_owner, ptr_dt_property_init_tmp );
	// 往PropertyState中写入初始数据
	this->Q3D_F_Model_Set( ptr_dt_property_init_tmp );
	*/
}

void UQ3D_CPPC_PropertyState::Q3D_F_Model_Set(UDataTable *ptr_dt_property_init)
{
	if (!this->Ptr_U_PropertyState)
	{
		Q3D_LOG(Warning, "Invalid_Ptr_U_PropertyState ");
		return;
	}
	if (!ptr_dt_property_init)
	{
		Q3D_LOG(Log, "Invalid_Ptr_DT_PropertyInit");
		return;
	}

	/* 一种读法
	TArray<FName> array_name_key = ptr_dt_property_init->GetRowNames();
	FString string_context;
	for ( auto& one : array_name_key )
	{
		FQ3D_CPPS_PropertyInit* ptr_s_property_init = ptr_dt_property_init->FindRow<FDataTableTestData>( one, string_context );
		if ( ptr_s_property_init ){
			// Q3D_LOG( Verbose, "Load_" \
			// +	StaticEnum<EQ3D_CPPE_PropertyName>()->GetNameStringByValue( (uint8)(ptr_s_property_init->Enum_PropertyName) ) \
			// +	"(" + FString::FromInt( ptr_s_property_init->Int_Min ) \
			// +	"," + FString::FromInt( ptr_s_property_init->Int_Max ) \
			// +	"," + ( ptr_s_property_init->Bool_Active ? "true" : "false" ) \
			// +	"," + StaticEnum<EQ3D_CPPE_PropertyInit>()->GetNameStringByValue( (uint8)(ptr_s_property_init->Enum_PropertyInit) ) \
			// +	"," + FString::FromInt( ptr_s_property_init->Int_Value ) \
			// +	")" \
			// );
		}
		if( ! ptr_s_property_init->Bool_Active ){
			continue;
		}
		UQ3D_CPPU_PropertyPLIPro* ptr_u_property_pli_pro_tmp;
		FString string_log_tmp;
		this->Ptr_U_PropertyState->Q3D_F_PropertyPLIPro_Create( \
			ptr_s_property_init->Enum_PropertyName, \
			ptr_s_property_init->Int_Min, \
			ptr_s_property_init->Int_Max, \
			ptr_s_property_init->Enum_PropertyInit, \
			ptr_s_property_init->Int_Value, \
			ptr_u_property_pli_pro_tmp, \
			string_log_tmp \
		);
		if( ! ptr_u_property_pli_pro_tmp ){
			Q3D_LOG( Warning, string_log_tmp );
		}
	}
	*/

	// 另一种读法
	for (auto one : ptr_dt_property_init->GetRowMap())
	{
		// one.Key has the key from first column of the CSV file
		// one.Value has a pointer to a struct of data. You can safely cast one to your actual type, e.g FMyStruct* data = (FMyStruct*)(one.Value);
		FString name_key = one.Key.ToString();
		FQ3D_CPPS_PropertyInit *ptr_s_property_init = (FQ3D_CPPS_PropertyInit *)(one.Value);
		// Q3D_LOG( Verbose, "Load_" \
		// +	StaticEnum<EQ3D_CPPE_PropertyName>()->GetNameStringByValue( (uint8)(ptr_s_property_init->Enum_PropertyName) ) \
		// +	"(" + FString::FromInt( ptr_s_property_init->Int_Min ) \
		// +	"," + FString::FromInt( ptr_s_property_init->Int_Max ) \
		// +	"," + ( ptr_s_property_init->Bool_Active ? "true" : "false" ) \
		// +	"," + StaticEnum<EQ3D_CPPE_PropertyInit>()->GetNameStringByValue( (uint8)(ptr_s_property_init->Enum_PropertyInit) ) \
		// +	"," + FString::FromInt( ptr_s_property_init->Int_Value ) \
		// +	")" \
		// );
		if (!ptr_s_property_init->Bool_Active)
		{
			continue;
		}
		UQ3D_CPPU_PropertyPLIPro *ptr_u_property_pli_pro_tmp;
		FString string_log_tmp;
		this->Ptr_U_PropertyState->Q3D_F_PropertyPLIPro_Create(
			ptr_s_property_init->Enum_PropertyName,
			ptr_s_property_init->Int_Min,
			ptr_s_property_init->Int_Max,
			ptr_s_property_init->Enum_PropertyInit,
			ptr_s_property_init->Int_Value,
			ptr_u_property_pli_pro_tmp,
			string_log_tmp);
		if (!ptr_u_property_pli_pro_tmp)
		{
			Q3D_LOG(Warning, string_log_tmp);
		}
	}

	Q3D_LOG(Log, "PropertyState_Inited_With_[" + FString::FromInt(this->Ptr_U_PropertyState->Map_PropertyName_To_Ptr_U_PropertyPLIPro.Num()) + "]_PropertyPLIPro");
}

void UQ3D_CPPC_PropertyState::Q3D_F_Property_Bind_Max_To_Now(EQ3D_CPPE_PropertyName enum_property_name_max, EQ3D_CPPE_PropertyName enum_property_name_now)
{
	UQ3D_CPPU_PropertyPLIPro *ptr_u_property_pli_pro_max;
	FString string_log_max;
	this->Ptr_U_PropertyState->Q3D_F_PropertyPLIPro_Get(enum_property_name_max, ptr_u_property_pli_pro_max, string_log_max);
	if (!ptr_u_property_pli_pro_max)
	{
		Q3D_LOG(Warning, string_log_max);
		return;
	}
	UQ3D_CPPU_PropertyPLIPro *ptr_u_property_pli_pro_now;
	FString string_log_now;
	this->Ptr_U_PropertyState->Q3D_F_PropertyPLIPro_Get(enum_property_name_now, ptr_u_property_pli_pro_now, string_log_now);
	if (!ptr_u_property_pli_pro_now)
	{
		Q3D_LOG(Warning, string_log_now);
		return;
	}
	ptr_u_property_pli_pro_max->Q3D_ED_ValuePro_Reset.AddDynamic(ptr_u_property_pli_pro_now, &UQ3D_CPPU_PropertyPLIPro::Q3D_FD_Max_SetScale_Pro);
	return;
}

void UQ3D_CPPC_PropertyState::Q3D_F_Create_Hit_On_Now_By_Spd(EQ3D_CPPE_PropertyName enum_property_name_spd, EQ3D_CPPE_PropertyName enum_property_name_now, float float_hit_interval, UPARAM(DisplayName = "ptr_u_hit") UQ3D_CPPU_Hit *&ptr_u_hit)
{
	if (!this->GetOwner())
	{
		Q3D_LOG(Warning, "Owner_Not_Ready");
		return;
	}
	UQ3D_CPPU_PropertyPLIPro *ptr_u_property_pli_pro_spd;
	FString string_log_spd;
	this->Ptr_U_PropertyState->Q3D_F_PropertyPLIPro_Get(enum_property_name_spd, ptr_u_property_pli_pro_spd, string_log_spd);
	if (!ptr_u_property_pli_pro_spd)
	{
		Q3D_LOG(Warning, string_log_spd);
		return;
	}
	UQ3D_CPPU_Hit *ptr_u_hit_tmp = NewObject<UQ3D_CPPU_Hit>(this->GetOwner());
	ptr_u_hit_tmp->Name_Id = FName(FGuid::NewGuid().ToString());
	ptr_u_hit_tmp->Enum_PropertyName = enum_property_name_now;
	ptr_u_hit_tmp->Q3D_F_HitMaker_Set(this->GetOwner(), ptr_u_hit_tmp);
	ptr_u_hit_tmp->Q3D_F_HitCauser_Set(this->GetOwner(), ptr_u_hit_tmp);
	ptr_u_hit_tmp->Q3D_F_HitType_SetRecover(ptr_u_hit_tmp);
	ptr_u_hit_tmp->Q3D_F_HitMode_SetHitInfinite(float_hit_interval, ptr_u_hit_tmp);
	ptr_u_hit_tmp->Q3D_F_HitValue_SetInt(ptr_u_property_pli_pro_spd->Int_ValuePro, ptr_u_hit_tmp);
	bool bool_success;
	FString string_log_hit;
	ptr_u_hit_tmp->Q3D_F_SetToTarget(this->GetOwner(), bool_success, string_log_hit);
	ptr_u_hit = ptr_u_hit_tmp;
	return;
}
